package redis

import "encoding/binary"

const (
	maxMetaDataSize   = 1 + binary.MaxVarintLen64*2 + binary.MaxVarintLen32
	extraListMetaSize = binary.MaxVarintLen64 * 2
)

// metadata 元信息
type metadata struct {
	dataType byte   // 数据类型
	expire   int64  // 过期时间
	version  int64  // 版本号
	size     uint32 // 数据量大小
	head     uint64 // List 结构头指针
	tail     uint64 // List 结构尾指针
}

// encode 元信息 metadata 编码
func (m *metadata) encode() []byte {
	var size = maxMetaDataSize
	if m.dataType == List {
		size += extraListMetaSize
	}
	buf := make([]byte, size)

	buf[0] = m.dataType
	var idx = 1
	idx += binary.PutVarint(buf[idx:], m.expire)
	idx += binary.PutVarint(buf[idx:], m.version)
	idx += binary.PutVarint(buf[idx:], int64(m.size))
	if m.dataType == List {
		idx += binary.PutVarint(buf[idx:], int64(m.head))
		idx += binary.PutVarint(buf[idx:], int64(m.tail))
	}

	return buf[:idx]
}

// decodeMetadata 解码元信息 metadata
func decodeMetadata(buf []byte) *metadata {
	dataType := buf[0]
	var idx = 1
	expire, n := binary.Varint(buf[idx:])
	idx += n
	version, n := binary.Varint(buf[idx:])
	idx += n
	size, n := binary.Varint(buf[idx:])
	idx += n

	var head, tail int64
	if dataType == List {
		head, n = binary.Varint(buf[idx:])
		idx += n
		tail, _ = binary.Varint(buf[idx:])
	}
	return &metadata{
		dataType: dataType,
		expire:   expire,
		version:  version,
		size:     uint32(size),
		head:     uint64(head),
		tail:     uint64(tail),
	}
}
